home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1995 June: Reference Library / Dev.CD Jun 95 / Dev.CD Jun 95.toast / What's New? / New System Software Extensions / QuickDraw 3D ß / Programming / SampleCode / TriGrids / Sources / TriGridShell.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-16  |  17.8 KB  |  693 lines  |  [TEXT/MPS ]

  1. //
  2. // This is box, the QuickDraw 3D starter program.  Written for the
  3. // Getting started with QuickDraw 3D Develop article.  This app does not have 
  4. // graceful error handling - it's putpose is to illustrate a very basic QuickDraw 
  5. // 3D program.
  6. //
  7. // Nick Thompson - January 6th 1994
  8. //
  9. // Modification History:
  10. //
  11. //    1/6/95        nick    initial version based on cube
  12. //    12/31/94    nick    cube modifications for QuickDraw 3d sample code
  13. //    03/22/95    rdd        adapted from BoxShell.c: added simple picking
  14. //                        and trigrid selection via number keys
  15. //    04/12/95    rdd        added SetCameraLocation.
  16. //    04/14/95    rdd     added menu support.
  17. //  
  18.  
  19.  
  20. // system headers
  21. #include <Desk.h>
  22. #include <Dialogs.h>
  23. #include <DiskInit.h>
  24. #include <Fonts.h>
  25. #include <Menus.h>
  26. #include <PictUtil.h>
  27. #include <QDOffScreen.h>
  28. #include <QuickDraw.h>
  29. #include <Resources.h>
  30. #include <SegLoad.h>
  31. #include <StandardFile.h>
  32. #include <TextEdit.h>
  33. #include <ToolUtils.h>
  34.  
  35. // for QuickDraw 3D
  36. #include "QD3D.h"
  37. #include "QD3DMath.h"
  38. #include "QD3DCamera.h"
  39. #include "QD3DDrawContext.h"
  40. #include "QD3DShader.h"
  41. #include "QD3DTransform.h"
  42. #include "QD3DGroup.h"
  43. #include "QD3DPick.h"
  44.  
  45.  
  46. #include "TriGridShell.h"
  47. #include "TriGrid3DSupport.h"
  48. #include "GeometrySample.h"
  49. #include "Textures2.h"
  50.  
  51. //-------------------------------------------------------------------------------------------
  52.  
  53. struct _documentRecord {
  54.     TQ3ViewObject    fView ;                    // the view for the scene
  55.     TQ3GroupObject    fModel ;                // object in the scene being modelled
  56.     TQ3StyleObject    fInterpolation ;        // interpolation style used when rendering
  57.     TQ3StyleObject    fBackFacing ;            // whether to draw shapes that face away from the camera
  58.     TQ3StyleObject    fFillStyle ;            // whether drawn as solid filled object or decomposed to components
  59.     TQ3Matrix4x4    fRotation ;                // the transform for the model
  60.     unsigned short    fGeometryNum ;            // triGrid geometry 1-9 (menu item number)
  61.     unsigned short    fTextureType ;            // method of uv parameterization for texture (menu item number)
  62.     unsigned short    fPictureNum ;            // PICT (menu item number)
  63. };
  64.  
  65. typedef struct _documentRecord DocumentRec, *DocumentPtr, **DocumentHdl ;
  66.  
  67.  
  68. //-------------------------------------------------------------------------------------------
  69. // function prototypes
  70.  
  71. static void         InitToolbox( void ) ;
  72. static Boolean        SetUpMenus (void) ;
  73. static void            IntializeMenuItems (DocumentPtr theDocument) ;
  74. static void         MainEventLoop( void ) ;
  75. static void         HandleKeyPress(EventRecord *pEvent) ;
  76. static void            DoAboutBox (void);
  77. static void            DoMenuCommand (long menuResult) ;
  78. static void         HandleOSEvent(EventRecord *event) ;
  79. static void            InitDocumentData( DocumentPtr theDocument ) ;
  80. static TQ3Status    DocumentDraw3DData( DocumentPtr theDocument ) ;
  81. static void            DisposeDocumentData( DocumentPtr theDocument) ;
  82. static void            SetCameraLocation (TQ3ViewObject view, float x, float y, float z);
  83. static void            ChangeGeometry (DocumentPtr theDocument) ;
  84. static void            DoPicking(EventRecord *event) ;
  85.  
  86.  
  87. //-------------------------------------------------------------------------------------------
  88. //
  89.  
  90. Boolean         gQuitFlag         = false ;
  91. WindowPtr        gMainWindow        = nil ;
  92. DocumentRec        gDocument ;
  93. Handle            ghMenuBar ;
  94. short            gNumPictures ;
  95.  
  96.  
  97. //-------------------------------------------------------------------------------------------
  98. // main()
  99. // entry point for the application, initialize the toolbox, initialize QuickDraw 3D
  100. // and enter the main event loop.  On exit from the main event loop, we want to call
  101. // the QuickDraw 3D exit function to clean up QuickDraw 3d.
  102.  
  103. void main(void)
  104. {
  105.     TQ3Status    myStatus;
  106.  
  107.     InitToolbox() ;
  108.     SetUpMenus () ;
  109.  
  110.     //    Initialize QuickDraw 3D, open a connection to the QuickDraw 3D library
  111.     myStatus = Q3Initialize();
  112.     if ( myStatus == kQ3Failure )
  113.         DebugStr("\pErInitialize returned failure.");            
  114.  
  115.     // set up our globals
  116.     gQuitFlag = false ;
  117.     gMainWindow = GetNewCWindow(kWindowRsrcID, nil, (WindowPtr)-1);
  118.  
  119.     InitDocumentData( &gDocument ) ;
  120.     IntializeMenuItems ( &gDocument ) ;
  121.  
  122.     MainEventLoop();
  123.     
  124.     DisposeDocumentData( &gDocument ) ;
  125.     
  126.     //    Close our connection to the QuickDraw 3D library
  127.     myStatus = Q3Exit();
  128.     if ( myStatus == kQ3Failure )
  129.         DebugStr("\pErExit returned failure.");
  130.     
  131. }
  132.  
  133. //-------------------------------------------------------------------------------------------
  134. //
  135.  
  136. void InitDocumentData( DocumentPtr theDocument ) 
  137. {
  138.     // sets up the 3d data for the scene
  139.     // Create view for QuickDraw 3D.
  140.     theDocument->fView = MyNewView( (WindowPtr)gMainWindow ) ;
  141.  
  142.     // the drawing styles:
  143.     theDocument->fInterpolation = Q3InterpolationStyle_New(kQ3InterpolationStyleNone) ;
  144.     theDocument->fBackFacing = Q3BackfacingStyle_New(kQ3BackfacingStyleBoth ) ;
  145.     theDocument->fFillStyle = Q3FillStyle_New(kQ3FillStyleFilled ) ;
  146.  
  147.     // set the rotation matrix the identity matrix
  148.     Q3Matrix4x4_SetIdentity(&theDocument->fRotation);        
  149.  
  150.     theDocument->fGeometryNum = iFlat ;
  151.     theDocument->fTextureType = iNoTexture ;
  152.     theDocument->fPictureNum  = iPictureFirst ;
  153.  
  154.     // the main display group:
  155.     theDocument->fModel = MyNewModel() ;
  156.     ChangeGeometry (theDocument);
  157. }
  158.  
  159. void DisposeDocumentData( DocumentPtr theDocument)
  160. {
  161.     Q3Object_Dispose(theDocument->fView) ;                // the view for the scene
  162.     Q3Object_Dispose(theDocument->fModel) ;                // object in the scene being modelled
  163.     Q3Object_Dispose(theDocument->fInterpolation) ;        // interpolation style used when rendering
  164.     Q3Object_Dispose(theDocument->fBackFacing) ;        // whether to draw shapes that face away from the camera
  165.     Q3Object_Dispose(theDocument->fFillStyle) ;            // whether drawn as solid filled object or decomposed to components
  166.  
  167. }
  168. //-----------------------------------------------------------------------------
  169. // 
  170.  
  171. TQ3Status DocumentDraw3DData( DocumentPtr theDocument )
  172. {    
  173.     Q3View_StartRendering(theDocument->fView );
  174.     do {
  175.         Q3Style_Submit( theDocument->fInterpolation, theDocument->fView );
  176.         Q3Style_Submit( theDocument->fBackFacing, theDocument->fView );
  177.         Q3Style_Submit( theDocument->fFillStyle, theDocument->fView );
  178.         Q3MatrixTransform_Submit( &theDocument->fRotation, theDocument->fView );
  179.         Q3DisplayGroup_Submit( theDocument->fModel, theDocument->fView );
  180.     } while (Q3View_EndRendering(theDocument->fView) == kQ3ViewStatusRetraverse );
  181.     return kQ3Success ;
  182. }
  183.  
  184.  
  185. //----------------------------------------------------------------------------------
  186. //
  187. void InitToolbox()
  188. {
  189.     Handle        menuBar = nil;
  190.  
  191.     MaxApplZone() ;
  192.     MoreMasters() ; MoreMasters() ; MoreMasters() ; 
  193.     
  194.     InitGraf( &qd.thePort );
  195.     InitFonts();
  196.     InitWindows();
  197.     InitCursor();
  198.  
  199.     FlushEvents( everyEvent, 0 ) ;
  200.     // initialize application globals
  201.     
  202.     gQuitFlag = false;
  203.     
  204. }
  205.  
  206.  
  207. //-------------------------------------------------------------------------------------------
  208. //
  209. Boolean SetUpMenus (void)
  210. {
  211.     Boolean        goodMenus;
  212.  
  213.     goodMenus = true;
  214.  
  215.     ghMenuBar = GetNewMBar (kMenuBarRsrc);
  216.     if (ghMenuBar != nil)
  217.     {
  218.         SetMenuBar (ghMenuBar);
  219.         AddResMenu (GetMenuHandle (mApple), (ResType) 'DRVR');
  220.         DrawMenuBar ();
  221.     }
  222.     else
  223.     {
  224.         DebugStr ("\pSetUpMenus: Couldn't find menu bar.");
  225.         ghMenuBar = nil;
  226.         goodMenus = false;
  227.     }
  228.  
  229.      return (goodMenus);
  230. }
  231.  
  232.  
  233. //-------------------------------------------------------------------------------------------
  234. //
  235. void IntializeMenuItems (DocumentPtr theDocument)
  236. {
  237.     MenuHandle    hMenu;
  238.     Str255        menuPrefix = {"\pPicture "},
  239.                 itemText,
  240.                 numString;
  241.     long        item;
  242.     short        rsrcID;
  243.     ResType        rsrcType;
  244.     Handle        hPict;
  245.  
  246.     hMenu = GetMHandle(mTexture);
  247.  
  248.     gNumPictures = Count1Resources ('PICT');
  249.  
  250.     /* PICT resources to be used as textures must be numbered starting with kFirstPICTRsrcID */
  251.     SetResLoad (false);
  252.     for (item = 0; item < gNumPictures; item++)
  253.     {
  254.         itemText[0] = 0;
  255.  
  256.         hPict = GetResource ('PICT', kFirstPICTRsrcID + item);
  257.         if (hPict != NULL)
  258.             GetResInfo (hPict, &rsrcID, &rsrcType, itemText);
  259.         else
  260.             break;
  261.  
  262.         if (itemText[0] == 0)
  263.         {
  264.             BlockMove ((Ptr) menuPrefix, (Ptr) itemText, (Size) menuPrefix[0]+1);
  265.             NumToString (item+1, numString);
  266.             itemText[0] += numString[0];
  267.             BlockMove ((Ptr) &numString[1], (Ptr) itemText[itemText[0]+1], (Size) numString[0]);
  268.         }
  269.  
  270.         AppendMenu (hMenu, itemText);
  271.     }
  272.     SetResLoad (true);
  273.  
  274.     gNumPictures = item;
  275.  
  276.     if (theDocument->fTextureType == iNoTexture)
  277.     {
  278.         for (item = iPictureFirst; item < iPictureFirst + gNumPictures; item++)
  279.             DisableItem(hMenu, item);
  280.     }
  281.  
  282.  
  283.     CheckItem (GetMHandle (mGeometry), theDocument->fGeometryNum, true);
  284.     CheckItem (hMenu, theDocument->fTextureType, true);
  285.     CheckItem (hMenu, theDocument->fPictureNum,  true);
  286. }
  287.  
  288.  
  289. //-------------------------------------------------------------------------------------------
  290. //
  291. void MainEventLoop()
  292. {
  293.     EventRecord     event;
  294.     WindowPtr       window;
  295.     short           thePart;
  296.     Rect            screenRect, updateRect;
  297.     Point            aPoint = {100, 100};
  298.     
  299.  
  300.     while( !gQuitFlag )
  301.     {
  302.         if (WaitNextEvent( everyEvent, &event, 0, nil ))
  303.         {
  304.  
  305.             switch (event.what) {
  306.                 case mouseDown:
  307.                 
  308.                     thePart = FindWindow( event.where, &window );
  309.                     
  310.                     switch( thePart ) {
  311.                         case inMenuBar: 
  312.                             DoMenuCommand (MenuSelect (event.where));
  313.                             break;
  314.  
  315.                         case inSysWindow:
  316.                             SystemClick (&event, window);
  317.                             break;
  318.  
  319.                         case inDrag:
  320.                             screenRect = (**GetGrayRgn()).rgnBBox;
  321.                             DragWindow( window, event.where, &screenRect );
  322.                             break ;
  323.                     
  324.                         case inContent:
  325.                             if (window != FrontWindow())
  326.                                 SelectWindow( window );
  327.                                 DoPicking(&event);
  328.                             break ;
  329.                     
  330.                         case inGoAway:
  331.                             if (TrackGoAway( window, event.where )) {
  332.                                 DisposeWindow ( window );
  333.                                 gQuitFlag = true;
  334.                             }
  335.                             break ;
  336.                             
  337.                         default:
  338.                         case inGrow:
  339.                         case inZoomIn:
  340.                         case inZoomOut:
  341.                             break ;
  342.                     }
  343.                     break ;
  344.                             
  345.                         
  346.                 case updateEvt:
  347.                     window = (WindowPtr)event.message;
  348.                     updateRect = (**(window->visRgn)).rgnBBox;
  349.                     SetPort( window ) ;
  350.                     BeginUpdate( window );
  351.                     DocumentDraw3DData( &gDocument ) ;
  352.                     EndUpdate( window );
  353.                     break ;
  354.                     
  355.                 case keyDown:
  356.                 case autoKey:
  357.                     HandleKeyPress(&event);
  358.                     break;
  359.                     
  360.                 case diskEvt:
  361.                     if ( HiWord(event.message) != noErr ) 
  362.                         (void) DIBadMount(aPoint, event.message);
  363.                     break;
  364.                     
  365.                 case osEvt:
  366.                 case activateEvt:
  367.                     break;
  368.  
  369.  
  370.             }
  371.         }
  372.         else {
  373.             // we received a null event, rotate the cube
  374.             TQ3Matrix4x4    tmp;
  375.             Rect            theRect = ((GrafPtr)gMainWindow)->portRect ;
  376.             
  377.             SetPort((GrafPtr)gMainWindow) ;
  378.             Q3Matrix4x4_SetRotate_XYZ(&tmp, 0.1, 0.12, 0.08);
  379.             Q3Matrix4x4_Multiply(&gDocument.fRotation, &tmp, &gDocument.fRotation);
  380.  
  381.             InvalRect( &theRect ) ;
  382.         }
  383.     }
  384. }
  385.  
  386.  
  387. //-------------------------------------------------------------------------------------------
  388. //
  389. void HandleKeyPress(EventRecord *pEvent)
  390. {
  391.     char            charCode;
  392.  
  393.     charCode = pEvent->message & charCodeMask;
  394.  
  395.     if (pEvent->modifiers & btnState)
  396.     {
  397.         /* Button is UP with a key */
  398.         if (pEvent->modifiers & cmdKey)
  399.         {
  400.             DoMenuCommand (MenuKey (charCode));
  401.         }
  402.     }
  403.     else
  404.     {
  405.         /* Button is DOWN with a key */
  406.     }
  407. }
  408.  
  409.  
  410. //-------------------------------------------------------------------------------------------
  411. //
  412. void DoAboutBox (void)
  413. {
  414.     DialogPtr    theDialog;
  415.     short        itemHit;
  416.  
  417.     theDialog = GetNewDialog(kDialogRsrcID, nil, (WindowPtr)-1);
  418.     if (theDialog == nil)
  419.         return;
  420.         
  421.     do
  422.     {
  423.         ModalDialog (nil, &itemHit);
  424.     }
  425.     while (itemHit != ok);
  426.  
  427.     DisposeDialog (theDialog);
  428. }
  429.  
  430.  
  431. //-------------------------------------------------------------------------------------------
  432. //
  433. void DoMenuCommand (long menuResult)
  434. {
  435.     short        menuID,
  436.                 itemNumber;
  437.  
  438.     if (! menuResult)
  439.         return;
  440.  
  441.     menuID       = HiWord (menuResult);
  442.     itemNumber = LoWord (menuResult);
  443.  
  444.     switch (menuID)
  445.     {
  446.         case mApple:
  447.             switch (itemNumber)
  448.             {
  449.             case iAbout:
  450.                 DoAboutBox();
  451.             break;
  452.  
  453.             default:
  454.                 {
  455.                     MenuHandle    hMenu;
  456.                     Str255        deskAccName;
  457.                     GrafPtr        oldPort;
  458.  
  459.                     hMenu = GetMHandle (menuID);
  460.                     if (hMenu != nil)
  461.                     {
  462.                         GetPort (&oldPort);
  463.  
  464.                         GetItem (hMenu, itemNumber, deskAccName);
  465.                         (void) OpenDeskAcc (deskAccName);
  466.                         SetPort (oldPort);
  467.                     }
  468.                 }
  469.                 break;
  470.             }
  471.             break;
  472.  
  473.         case mFile:
  474.             switch (itemNumber)
  475.             {
  476.             case iNew:            break;
  477.             case iOpen:            break;
  478.             case iClose:        break;
  479.  
  480.             case iQuit:
  481.                 gQuitFlag = true;break;
  482.  
  483.             default: SysBeep(1);break;
  484.             }
  485.             break;
  486.  
  487.         case mEdit:
  488.             if (! SystemEdit (itemNumber - 1))
  489.                 switch (itemNumber)
  490.                 {
  491.                 case iUndo:        break;
  492.                 case iCut:        break;
  493.                 case iCopy:        break;
  494.                 case iPaste:    break;
  495.                 case iClear:    break;
  496.                 }
  497.             break;
  498.  
  499.         case mGeometry:
  500.             if (itemNumber != gDocument.fGeometryNum)
  501.             {
  502.                 CheckItem (GetMHandle (mGeometry), gDocument.fGeometryNum, false);
  503.                 gDocument.fGeometryNum = itemNumber;
  504.                 CheckItem (GetMHandle (mGeometry), gDocument.fGeometryNum, true);
  505.                 ChangeGeometry (&gDocument);
  506.             }
  507.             break;
  508.  
  509.         case mTexture:
  510.             if (itemNumber >= iNoTexture  &&  itemNumber <= iFaceTexture)
  511.             {
  512.                 if (itemNumber != gDocument.fTextureType)
  513.                 {
  514.                     long    item;
  515.  
  516.                     if (gDocument.fTextureType == iNoTexture)
  517.                     {
  518.                         for (item = iPictureFirst; item < iPictureFirst + gNumPictures; item++)
  519.                             EnableItem(GetMHandle (menuID), item);
  520.                     }
  521.                     else
  522.                     if (itemNumber == iNoTexture)
  523.                     {
  524.                         for (item = iPictureFirst; item < iPictureFirst + gNumPictures; item++)
  525.                             DisableItem(GetMHandle (menuID), item);
  526.                     }
  527.  
  528.                     CheckItem (GetMHandle (mTexture), gDocument.fTextureType, false);
  529.                     gDocument.fTextureType = itemNumber;
  530.                     CheckItem (GetMHandle (mTexture), gDocument.fTextureType, true);
  531.                     ChangeGeometry (&gDocument);
  532.                 }
  533.             }
  534.             else
  535.             if (itemNumber >= iPictureFirst  && itemNumber <= iPictureFirst + gNumPictures - 1)
  536.             {
  537.                 if (itemNumber != gDocument.fPictureNum)
  538.                 {
  539.                     CheckItem (GetMHandle (mTexture), gDocument.fPictureNum, false);
  540.                     gDocument.fPictureNum = itemNumber;
  541.                     CheckItem (GetMHandle (mTexture), gDocument.fPictureNum, true);
  542.                     ChangeGeometry (&gDocument);
  543.                 }
  544.             }
  545.             break;
  546.  
  547.         default:
  548.             break;
  549.  
  550.     }  /*  switch (menuID)  */
  551.  
  552.     HiliteMenu (0);
  553. }
  554.  
  555.  
  556. //-------------------------------------------------------------------------------------------
  557. //
  558. void SetCameraLocation (TQ3ViewObject view, float x, float y, float z)
  559. {
  560.     TQ3CameraObject    camera;
  561.     TQ3CameraData    cameraData;
  562.  
  563.     Q3View_GetCamera(view, &camera);
  564.     if (camera != nil)
  565.     {
  566.         Q3Camera_GetData(camera, &cameraData);
  567.         Q3Point3D_Set(&cameraData.placement.cameraLocation, x, y, z);
  568.         Q3Camera_SetData(camera, &cameraData);
  569.         Q3Object_Dispose(camera);
  570.     }
  571. }
  572.  
  573.  
  574. //-------------------------------------------------------------------------------------------
  575. //
  576. void ChangeGeometry (DocumentPtr theDocument)
  577. {
  578.     TQ3Status            status;
  579.     TQ3Object            object;
  580.     TQ3GroupPosition    position;
  581.     unsigned long        triGridLibNum;
  582.  
  583.     if (theDocument->fModel == nil)
  584.         return;
  585.  
  586.     status = Q3Group_GetFirstPositionOfType(theDocument->fModel, kQ3ShapeTypeGeometry, &position);
  587.     if (status == kQ3Success  &&  position != nil)
  588.     {
  589.         object = Q3Group_RemovePosition(theDocument->fModel, position);
  590.         Q3Object_Dispose(object);
  591.         object = NULL;
  592.     }
  593.  
  594.     switch (theDocument->fTextureType)
  595.     {
  596.         case iNoTexture:        triGridLibNum = (theDocument->fGeometryNum-1) + kGeometryLibraryRange_Simple;            break;
  597.         case iGeometryTexture:    triGridLibNum = (theDocument->fGeometryNum-1) + kGeometryLibraryRange_UVGeoAttributes;    break;
  598.         case iFaceTexture:        triGridLibNum = (theDocument->fGeometryNum-1) + kGeometryLibraryRange_UVFaceAttributes;break;
  599.     }
  600.     object = NewLibraryTriGrid(triGridLibNum);
  601.     if (object == NULL)
  602.         return;
  603.     Q3Group_AddObject (theDocument->fModel, object);
  604.  
  605.     /* Add diffuse color if no texture */
  606.     if (theDocument->fTextureType == iNoTexture)
  607.     {
  608.         TQ3AttributeSet        attrSet;
  609.         TQ3ColorRGB            rgbColor;
  610.  
  611.         attrSet = Q3AttributeSet_New();
  612.         if (attrSet != NULL)
  613.         {
  614.             Q3ColorRGB_Set(&rgbColor, 0.0, 0.75, 0.75);
  615.             status = Q3AttributeSet_Add(attrSet, kQ3AttributeTypeDiffuseColor, &rgbColor);
  616.             if (status == kQ3Success)
  617.             {
  618.                 Q3Geometry_SetAttributeSet(object, attrSet);
  619.                 Q3Object_Dispose(attrSet);
  620.             }
  621.         }
  622.     }
  623.     else
  624.         /* Add texture shader */
  625.         AddResourceTextureToGroup(theDocument->fPictureNum - iPictureFirst + kFirstPICTRsrcID, theDocument->fModel);
  626.  
  627.     Q3Object_Dispose(object);
  628.  
  629.     /* (These cameral locations could be calculated) */
  630.     switch (theDocument->fGeometryNum)
  631.     {
  632.     case iFlat:            SetCameraLocation (theDocument->fView, 0.0, 0.0,  4.0);    break;
  633.     case iTorus:        SetCameraLocation (theDocument->fView, 0.0, 0.0, 10.0);    break;
  634.     case iWaveyTorus:    SetCameraLocation (theDocument->fView, 0.0, 0.0, 10.0);    break;
  635.     case iSplash:        SetCameraLocation (theDocument->fView, 0.0, 0.0, 25.0);    break;
  636.     case iSphere:        SetCameraLocation (theDocument->fView, 0.0, 0.0,  7.0);    break;
  637.     case iCone:            SetCameraLocation (theDocument->fView, 0.0, 0.0,  9.0);    break;
  638.     case iPipe:            SetCameraLocation (theDocument->fView, 0.0, 0.0, 10.0);    break;
  639.     case iSteps:        SetCameraLocation (theDocument->fView, 0.0, 0.0, 30.0);    break;
  640.     case iSpring:        SetCameraLocation (theDocument->fView, 0.0, 0.0, 11.0);    break;
  641.     }
  642. }
  643.  
  644.  
  645. //-------------------------------------------------------------------------------------------
  646. //
  647. void DoPicking(EventRecord *event)
  648. {
  649.     Point                    screenPoint;
  650.     TQ3WindowPointPickData    withData;
  651.     unsigned long            numPicked;
  652.     TQ3PickObject            pickObject;
  653.     TQ3Status                status;
  654.     TQ3ViewStatus            viewStatus;
  655.     
  656.     withData.data.sort             =    kQ3PickSortNone;
  657.     withData.data.numHitsToReturn=    kQ3ReturnAllHits;
  658.     withData.data.mask             =    kQ3PickDetailMaskObject;
  659.                                   
  660.     screenPoint = event->where;
  661.     GlobalToLocal (&screenPoint);
  662.     withData.point.x = screenPoint.h;
  663.     withData.point.y = screenPoint.v;
  664.  
  665.     withData.vertexTolerance = withData.edgeTolerance = 2.0;
  666.  
  667.     pickObject = Q3WindowPointPick_New(&withData);
  668.  
  669.     status = Q3View_StartPicking(gDocument.fView, pickObject);
  670.     if (status == kQ3Failure)
  671.         debugstr ("DoPicking: Q3View_StartPicking failed.");
  672.     do {
  673.         status = Q3DisplayGroup_Submit(gDocument.fModel, gDocument.fView);
  674.         if (status == kQ3Failure)
  675.             debugstr ("DoPicking: Q3View_StartPicking failed.");
  676.  
  677.         viewStatus = Q3View_EndPicking(gDocument.fView);
  678.     } while (viewStatus == kQ3ViewStatusRetraverse);
  679.  
  680.     if (viewStatus != kQ3ViewStatusDone)
  681.         debugstr ("DoPicking: Q3View_EndPicking failed.");
  682.  
  683.  
  684.     if (Q3Pick_GetNumHits(pickObject, &numPicked) && (numPicked != 0)) {
  685.         SetCursor(*GetCursor(plusCursor));
  686.         SysBeep(1);
  687.     } else {
  688.         SetCursor(&qd.arrow);
  689.     }
  690.  
  691.     Q3Object_Dispose(pickObject);
  692. }
  693.